package com.jerei.developer.utils;

import com.jerei.utils.UtilsCommon;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.io.*;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by sunfeihu on 2016/10/25.
 */
@Component
public class UtilsRoot {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    private Map<String, Object> rootMap = null;

    private Configuration configuration = null;

    private void initConfiguration() throws IOException {
        if (null == configuration) {
            configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
            configuration.setDefaultEncoding("utf-8");
            configuration.setOutputEncoding("utf-8");
            File folder = new File(this.getClass().getResource("/templates/").getPath());
            configuration.setDirectoryForTemplateLoading(folder);
            configuration.setObjectWrapper(new DefaultObjectWrapper(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS));
        }
    }

    /**
     * 获取当前数据库连接池的数据库名称
     *
     * @return 数据库名称
     */
    private String getDbName() {
        String dbName = "";
        Connection connection = null;
        try {
            connection = jdbcTemplate.getDataSource().getConnection();
            dbName = connection.getCatalog();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != connection) {
                try {
                    connection.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return dbName;
    }

    public void templateOut(String template, String outName, Map<String, Object> root, String pluginId) {
        try {
            this.initConfiguration();
            if (null == root) {
                root = new HashMap<String, Object>();
            }
            root.put("pluginId", pluginId);
            Template t = configuration.getTemplate(template, "utf-8");
            t.setOutputEncoding("utf-8");
            FileOutputStream fos = new FileOutputStream(new File(outName));
            OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
            BufferedWriter bw = new BufferedWriter(osw, 1024);
            t.process(root, bw);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 模板输出
     */
    public void templateOut(String template, String outName, String tableName, String folder, String pluginId) {
        try {
            this.initConfiguration();
            Map<String, Object> root = this.getRoot(tableName);
            root.put("pluginId", pluginId);
            Template t = configuration.getTemplate(template, "utf-8");
            t.setOutputEncoding("utf-8");
            //获取输出路径
            String outFile = this.getClass().getClassLoader().getResource("").getFile();
            outFile = outFile + File.separator + "output" + File.separator + folder;
            File outFolder = new File(outFile);
            if (!outFolder.exists()) {
                outFolder.mkdirs();
            }
            if (outName.equals("Dao") || outName.equals("Service")) {
                outFile = outFile + File.separator + "I" + UtilsCommon.getString(root.get("entityName")) + outName + ".java";
            } else {
                outFile = outFile + File.separator + UtilsCommon.getString(root.get("entityName")) + outName + ".java";
            }

            FileOutputStream fos = new FileOutputStream(outFile);
            OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
            BufferedWriter bw = new BufferedWriter(osw, 1024);
            t.process(root, bw);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取给模板的基本数据信息
     *
     * @return 封装后的数据信息
     */
    public Map<String, Object> getRoot(String tableName) {
        if (null != this.rootMap) {
            return this.rootMap;
        }
        String dbName = this.getDbName();
        String packageFolder = this.getPackageFolderByTableName(tableName);
        final String sql = " SELECT COLUMN_NAME as columnName,DATA_TYPE as dataType,COLUMN_COMMENT as columnComment FROM information_schema. COLUMNS WHERE table_name = '" + tableName + "' AND table_schema = '" + dbName + "' ";
        List<Map<String, Object>> fields = jdbcTemplate.queryForList(sql);
        String entityDesc = "";
        String insertField = "";
        String insertQField = "";
        String updateField = "";
        Boolean haveSid = false;
        List<Map<String, Object>> fieldsNoId = new ArrayList<Map<String, Object>>();
        if (null != fields && fields.size() > 0) {
            String columnName = "";
            for (Map<String, Object> m : fields) {
                columnName = UtilsCommon.getString(m.get("columnName"));
                if ("id".equals(columnName)) {
                    entityDesc = UtilsCommon.getString(m.get("columnComment"));
                }
                //如果包含站点ID
                if (columnName.equals("sid")) {
                    haveSid = true;
                }
                //进行JAVA数据类型转换
                m.put("javaType", this.getJavaType(UtilsCommon.getString(m.get("dataType"))));
                m.put("dbColumnName", columnName);
                //进行字段驼峰转换
                m.put("columnName", UtilsCommon.camelName(columnName));
                //进行getSet方法命名
                m.put("getSetName", this.firstUpper(UtilsCommon.camelName(columnName)));
                //进行JDBCTemplate数据类型转换
                m.put("mapperType", this.getMapperType(UtilsCommon.getString(m.get("dataType"))));
                if (!columnName.equals("id")) {
                    insertField += columnName + ",";
                    updateField += columnName + "=?,";
                    insertQField += "?,";
                    fieldsNoId.add(m);
                }
            }
        }
        String entityName = UtilsCommon.camelName(tableName);
        entityName = this.firstUpper(entityName);

        Map<String, Object> root = new HashMap<String, Object>();
        root.put("entityName", entityName);
        root.put("tableName", tableName);
        root.put("haveSid", haveSid);
        root.put("fields", fields);
        root.put("fieldsNoId", fieldsNoId);
        if (!"".equals(insertField) && insertField.indexOf(",") != -1) {
            insertField = insertField.substring(0, insertField.length() - 1);
            insertQField = insertQField.substring(0, insertQField.length() - 1);
            updateField = updateField.substring(0, updateField.length() - 1);
        }
        root.put("insertField", insertField);
        root.put("insertQField", insertQField);
        root.put("updateField", updateField);
        root.put("packageFolder", packageFolder);
        root.put("requestMapping", this.getRequestMapping(tableName));
        root.put("entityDesc", entityDesc);
        this.rootMap = root;
        return root;
    }

    /**
     * 获取spring的requestMapping路径
     *
     * @param tableName 表名
     * @return 路径
     */
    private String getRequestMapping(String tableName) {
        String requestMapping = "";
        String[] arr = tableName.split("_");
        if (null != arr && arr.length > 0) {
            for (int i = 0; i < arr.length; i++) {
                requestMapping += arr[i] + "/";
            }
            requestMapping = requestMapping.substring(0, requestMapping.length() - 1);
        }
        return "/" + requestMapping;
    }

    /**
     * 根据数据库表名获取包名
     *
     * @return 包名
     */
    private String getPackageFolderByTableName(String tableName) {
        String returnName = tableName;
        String[] returnNameArr = returnName.split("_");
        if (null != returnNameArr && returnNameArr.length > 1) {
            returnName = returnNameArr[0] + "." + returnNameArr[1];
        }
        return returnName;
    }

    /**
     * 是否为主从转换，如果满足主从转换，则关联实体
     *
     * @return 是否支持为主从转换
     */
    private Map<String, Object> masterAndSlave(Map<String, Object> m) {
        String columnName = UtilsCommon.getString(m.get("columnName"));
        //如果字段名称是站点ID
        if ("sid".equals(columnName)) {
            m.put("columnName", "website");
            m.put("getSetName", "WcmCommonWebsite");
            m.put("javaType", "com.jerei.wcm.common.WcmCommonWebsite");
            return m;
        }
        //如果字段名称是站群ID
        if ("gid".equals(columnName)) {
            m.put("columnName", "group");
            m.put("getSetName", "WcmCommonGroup");
            m.put("javaType", "com.jerei.wcm.common.WcmCommonGroup");
            return m;
        }
        //如果字段名称是省份ID
        if ("provicne_id".equals(columnName)) {
            m.put("columnName", "province");
            m.put("getSetName", "WcmCommonRegion");
            m.put("javaType", "com.jerei.wcm.common.WcmCommonRegion");
            return m;
        }
        //如果字段名称是城市ID
        if ("city_id".equals(columnName)) {
            m.put("columnName", "city");
            m.put("getSetName", "WcmCommonRegion");
            m.put("javaType", "com.jerei.wcm.common.WcmCommonRegion");
            return m;
        }
        //如果字段名称是区域ID
        if ("area_id".equals(columnName)) {
            m.put("columnName", "area");
            m.put("getSetName", "WcmCommonRegion");
            m.put("javaType", "com.jerei.wcm.common.WcmCommonRegion");
            return m;
        }
        return null;
    }

    /**
     * 将字符串首字母大写
     *
     * @param name 要处理的字符串
     * @return 处理后的字符串
     */
    private String firstUpper(String name) {
        String startName = name.substring(0, 1);
        name = startName.toUpperCase() + name.substring(1);
        return name;
    }

    /**
     * 根据数据库类型获取JAVA类型
     *
     * @param dbDataType 数据库数据类型
     * @return 转换后的JAVA数据类型
     */
    private String getJavaType(String dbDataType) {
        if ("text".equals(dbDataType) || "varchar".equals(dbDataType)) {
            return "String";
        }
        if ("int".equals(dbDataType)) {
            return "Integer";
        }
        if ("bigint".equals(dbDataType)) {
            return "Long";
        }
        if ("datetime".equals(dbDataType)) {
            return "java.util.Date";
        }
        return "String";
    }

    /**
     * 获取JDBCTemplate数据转换格式
     *
     * @param dbDataType 数据库类型
     * @return JDBCTemplate数据格式
     */
    private String getMapperType(String dbDataType) {
        if ("text".equals(dbDataType) || "varchar".equals(dbDataType)) {
            return "String";
        }
        if ("int".equals(dbDataType)) {
            return "Int";
        }
        if ("bigint".equals(dbDataType)) {
            return "Long";
        }
        if ("datetime".equals(dbDataType)) {
            return "Date";
        }
        return "String";
    }

}
